package com.im.imservice.handler;

/**
 * @author Huawei
 * @date 2023-08-11 14:15
 */

import com.im.client.AdminApi;
import com.im.imservice.config.CurrentChannelInfo;
import com.im.imservice.config.SpringBeanUtil;
import com.im.imservice.message.MessageService;
import com.pojo.UserInfo;
import com.utility.result.Result;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

import static io.netty.handler.codec.http.HttpHeaderNames.HOST;
import static io.netty.handler.codec.http.HttpMethod.GET;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * 客户端 服务端 握手handler
 */
@Slf4j
public class HandshakeHandler extends SimpleChannelInboundHandler<FullHttpRequest> {


    private WebSocketServerHandshaker handshaker;

    private static final String HTTP_REQUEST_STRING = "Authorization";

    private static AdminApi adminApi ;

    static {
        adminApi = SpringBeanUtil.getBean(AdminApi.class);
    }

    /**
     * 路径
     */
    private static final String WEBSOCKET_PATH = "/websocket";

    private Boolean isSuccess;


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest o) throws Exception {
        /**
         * 如果 当前消息传递的是 Http消息请求
         */
        if (o instanceof FullHttpRequest) {
            isSuccess = handleHttpRequest(channelHandlerContext, (FullHttpRequest) o);
        }else {
            /**
             * 如果不是 则调用下一个 handler处理请求
             */
            channelHandlerContext.fireChannelRead(((WebSocketFrame) o).retain());
        }

    }


    /**
     *  处理握手请求操作
     * @param ctx
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        Channel incoming = ctx.channel();
        log.info("收到" + incoming.remoteAddress() + " 握手请求");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(new TextWebSocketFrame(isSuccess?MessageService.ok():MessageService.err()));
    }

    /**
     *
     * @param ctx
     * @param req
     */
    private Boolean  handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
        // 判断是否正确的http请求
        if (!req.decoderResult().isSuccess()) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST));
            return false;
        }
        /**
         * 路径验证
         */
        if (!WEBSOCKET_PATH.equals(req.uri().substring(0,10))){
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND));
        }
        // 只允许GET方法。
        if (req.method() != GET) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
            return false;
        }

        if ("/favicon.ico".equals(req.uri()) || ("/".equals(req.uri()))) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND));
            return false;
        }

        QueryStringDecoder queryStringDecoder = new QueryStringDecoder(req.uri());
        Map<String, List<String>> parameters = queryStringDecoder.parameters();

        if (parameters.size() == 0 || !parameters.containsKey(HTTP_REQUEST_STRING)) {
            log.info(HTTP_REQUEST_STRING + "参数不可缺省");
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, INTERNAL_SERVER_ERROR));
            return false;
        }


        // Handshake
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, true);
        handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            //一个新的WebSocketServerHandshaker，用于请求的web套接字版本。如果不支持web套接字版本，则为空
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
            return false;
        } else {
            ChannelFuture channelFuture = handshaker.handshake(ctx.channel(), req);

            // 握手成功之后,业务逻辑
            if (channelFuture.isSuccess()) {
                String token = parameters.get(HTTP_REQUEST_STRING).get(0);
                Result<UserInfo>  userInfoResult = adminApi.userInfo(token);
                if (userInfoResult.getCode() == 200){
                    CurrentChannelInfo.setChannelGroupMap(userInfoResult.getData().getId()+"",ctx.channel());
                    return true;
                }
            }
            return false;
        }
    }


    private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
        if (res.status().code() != 200) {
            ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(), CharsetUtil.UTF_8);
            res.content().writeBytes(buf);
            buf.release();
//            HttpHeaderUtil.setContentLength(res, res.content().readableBytes());
        }

        ChannelFuture f = ctx.channel().writeAndFlush(res);
//        if (!HttpHeaderUtil.isKeepAlive(req) || res.status().code() != 200) {
//            f.addListener(ChannelFutureListener.CLOSE);
//        }
    }

    private static String getWebSocketLocation(FullHttpRequest req) {
        String location = req.headers().get(HOST) + WEBSOCKET_PATH;
        return "ws://" + location;
    }

}
